using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
using Voodoo.Sauce.Internal.Analytics;
using Voodoo.Sauce.Internal.Extension;
using Voodoo.Sauce.Internal.Utils;

namespace Voodoo.Sauce.Debugger
{
	public class EventConsoleListScreen : Screen
	{
		private const string DEFAULT_WRAPPER_NAME_FILTER = "VoodooAnalytics";

		[Header("EventConsole")]
		[SerializeField]
		private EventConsoleInformationScreen eventInformationScreen;

		[SerializeField]
		private EventConsoleFiltersScreen eventFiltersScreen;

		[SerializeField]
		private Transform sessionContainer;

		[SerializeField]
		private Button recordButton;

		[SerializeField]
		private Button flushButton;

		[SerializeField]
		private Button filterButton;

		[SerializeField]
		private Image recordingImage;

		[SerializeField]
		private Image pauseImage;

		[SerializeField]
		private Button recordAtStartupBtnOn;

		[SerializeField]
		private Button recordAtStartupBtnOff;

		[Header("Prefab")]
		[SerializeField]
		private EventConsoleItem eventLogItemPrefab;

		[SerializeField]
		private EventConsoleSessionItem sessionItemPrefab;

		private static readonly ConcurrentQueue<Action> _runOnMainThread = new ConcurrentQueue<Action>();

		private readonly Dictionary<string, EventConsoleItem> _eventDictionary = new Dictionary<string, EventConsoleItem>();

		private readonly Dictionary<string, EventConsoleSessionItem> _sessionDictionary = new Dictionary<string, EventConsoleSessionItem>();

		private readonly Stack<EventConsoleItem> _eventPool = new Stack<EventConsoleItem>();

		private void Awake()
		{
			recordButton.onClick.AddListener(RecordPressed);
			flushButton.onClick.AddListener(FlushLog);
			filterButton.onClick.AddListener(ShowFiltersScreen);
			recordAtStartupBtnOn.onClick.AddListener(OnRecordAtStartupBtnClick);
			recordAtStartupBtnOff.onClick.AddListener(OnRecordAtStartupBtnClick);
			eventFiltersScreen.EventConsoleListScreen = this;
		}

		private void Start()
		{
			RefreshEventLogToScreen();
			AnalyticsEventLogger.OnAnalyticsEventStateChanged += HandleNewEventEmitted;
		}

		private void OnDestroy()
		{
			AnalyticsEventLogger.OnAnalyticsEventStateChanged -= HandleNewEventEmitted;
			recordButton.onClick.RemoveListener(RecordPressed);
		}

		private void Update()
		{
			if (!_runOnMainThread.IsEmpty)
			{
				Action result;
				while (_runOnMainThread.TryDequeue(out result))
				{
					result?.Invoke();
				}
			}
		}

		private void OnEnable()
		{
			StartCoroutine(RefreshOnEnable());
			UpdateRecordAtStartupBtnDisplay();
			UpdateRecordButtonState();
		}

		private IEnumerator RefreshOnEnable()
		{
			yield return null;
			RefreshSessionsSize();
		}

		private static void EnableAnalyticsLoggingAndDebugging(bool isEnabled)
		{
			AnalyticsEventLogger.GetInstance().SetAnalyticsEventRecording(isEnabled);
		}

		private static void UpdateButtonState(bool enable, Selectable button, Graphic buttonIcon)
		{
			if (button.interactable != enable)
			{
				button.interactable = enable;
				ColorBlock colors = button.colors;
				buttonIcon.color = (enable ? colors.normalColor : colors.disabledColor);
			}
		}

		private void ShowFiltersScreen()
		{
			Debugger.Show(eventFiltersScreen);
		}

		internal void RefreshEventLogToScreen()
		{
			IEnumerable<DebugAnalyticsLog> localAnalyticsLog = AnalyticsEventLogger.GetInstance().GetLocalAnalyticsLog("VoodooAnalytics");
			bool interactable = localAnalyticsLog.Any();
			flushButton.interactable = interactable;
			filterButton.interactable = interactable;
			localAnalyticsLog = eventFiltersScreen.FilterEvents(localAnalyticsLog);
			foreach (KeyValuePair<string, EventConsoleItem> item in _eventDictionary.ToList())
			{
				item.Value.gameObject.SetActive(value: false);
				_eventDictionary.Remove(item.Key);
				_eventPool.Push(item.Value);
			}
			foreach (KeyValuePair<string, EventConsoleSessionItem> item2 in _sessionDictionary.ToList())
			{
				item2.Value.gameObject.SetActive(value: false);
			}
			foreach (DebugAnalyticsLog item3 in localAnalyticsLog)
			{
				CreateEvent(item3);
			}
		}

		private void HandleNewEventEmitted(DebugAnalyticsLog log, bool isUpdateFromExisting)
		{
			if (!log.WrapperName.Contains("VoodooAnalytics"))
			{
				return;
			}
			flushButton.interactable = true;
			filterButton.interactable = true;
			if (eventFiltersScreen.IsExcluded(log))
			{
				return;
			}
			if (UnityThreadExecutor.IsMainThread)
			{
				DisplayEvent(log);
				return;
			}
			_runOnMainThread.Enqueue(delegate
			{
				DisplayEvent(log);
			});
		}

		private void DisplayEvent(DebugAnalyticsLog log)
		{
			if (!_eventDictionary.ContainsKey(log.EventId))
			{
				CreateEvent(log);
			}
			else
			{
				UpdateEvent(log);
			}
		}

		private void CreateEvent(DebugAnalyticsLog log)
		{
			EventConsoleSessionItem eventConsoleSessionItem = (_sessionDictionary.ContainsKey(log.SessionId) ? _sessionDictionary[log.SessionId] : CreateSession(log.SessionId));
			EventConsoleItem eventConsoleItem;
			if (_eventPool.Count == 0)
			{
				eventConsoleItem = UnityEngine.Object.Instantiate(eventLogItemPrefab, eventConsoleSessionItem.GetContainer);
			}
			else
			{
				eventConsoleItem = _eventPool.Pop();
				eventConsoleItem.transform.SetParent(eventConsoleSessionItem.GetComponent<EventConsoleSessionItem>().GetContainer);
				eventConsoleSessionItem.gameObject.SetActive(value: true);
				eventConsoleItem.gameObject.SetActive(value: true);
			}
			_eventDictionary.Add(log.EventId, eventConsoleItem);
			eventConsoleItem.transform.SetAsFirstSibling();
			eventConsoleItem.UpdateData(log, delegate
			{
				ShowEventDescription(log);
			});
			eventConsoleItem.transform.RefreshHierarchySize();
		}

		private void ShowEventDescription(DebugAnalyticsLog log)
		{
			Debugger.Show(eventInformationScreen);
			eventInformationScreen.ShowEventDescription(log);
		}

		private void RefreshSessionsSize()
		{
			foreach (KeyValuePair<string, EventConsoleSessionItem> item in _sessionDictionary.ToList())
			{
				item.Value.GetContainer.RefreshHierarchySize();
			}
		}

		private void UpdateEvent(DebugAnalyticsLog log)
		{
			_eventDictionary.TryGetValue(log.EventId, out var value);
			if (value != null)
			{
				value.UpdateData(log, delegate
				{
					ShowEventDescription(log);
				});
			}
		}

		private EventConsoleSessionItem CreateSession(string sessionId)
		{
			EventConsoleSessionItem eventConsoleSessionItem = UnityEngine.Object.Instantiate(sessionItemPrefab, sessionContainer);
			eventConsoleSessionItem.transform.SetAsFirstSibling();
			_sessionDictionary.Add(sessionId, eventConsoleSessionItem);
			eventConsoleSessionItem.Initialize(_sessionDictionary.Count, sessionId);
			return eventConsoleSessionItem;
		}

		private void FlushLog()
		{
			AnalyticsEventLogger.GetInstance().FlushAnalyticsLogs();
			RefreshEventLogToScreen();
			RefreshSessionsSize();
		}

		private void RecordPressed()
		{
			EnableAnalyticsLoggingAndDebugging(!AnalyticsEventLogger.GetInstance().IsRecordingEvents);
			UpdateRecordButtonState();
		}

		private void OnRecordAtStartupBtnClick()
		{
			AnalyticsEventLogger.GetInstance().IsRecordingAtStartup = !AnalyticsEventLogger.GetInstance().IsRecordingAtStartup;
			UpdateRecordAtStartupBtnDisplay();
		}

		private void UpdateRecordAtStartupBtnDisplay()
		{
			bool isRecordingAtStartup = AnalyticsEventLogger.GetInstance().IsRecordingAtStartup;
			recordAtStartupBtnOn.gameObject.SetActive(isRecordingAtStartup);
			recordAtStartupBtnOff.gameObject.SetActive(!isRecordingAtStartup);
		}

		private void UpdateRecordButtonState()
		{
			bool isRecordingEvents = AnalyticsEventLogger.GetInstance().IsRecordingEvents;
			recordingImage.gameObject.SetActive(!isRecordingEvents);
			pauseImage.gameObject.SetActive(isRecordingEvents);
		}
	}
}
